﻿using Elastic.Clients.Elasticsearch;
using Elastic.Clients.Elasticsearch.Aggregations;
using Elastic.Clients.Elasticsearch.Analysis;
using Elastic.Clients.Elasticsearch.Core.Bulk;
using Elastic.Clients.Elasticsearch.Nodes;
using Elastic.Clients.Elasticsearch.QueryDsl;
using Elastic.Transport;
using Elasticsearch.Configuration;
using Elasticsearch.Model;
using Microsoft.Extensions.Options;
using System;
using System.Linq;
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Text.RegularExpressions;

namespace Elasticsearch.Service
{
    public class UserService : IUserService
    {
        private readonly ElasticsearchClient _client;

        public UserService(ElasticsearchClient client)
        {
            _client = client;
        }

        //// 创建索引（可选：仅首次）
        //public async Task<bool> CreateUserIndexAsync()
        //{
        //    var exists = await _client.Indices.ExistsAsync("users");
        //    if (exists.Exists) return true;

        //    var response = await _client.Indices.CreateAsync("users", c => c
        //        .Mappings(m => m
        //            .Properties(p => p
        //                .Keyword(k => k.Name("id"))
        //                .Text(t => t.Name("username"))
        //                .Keyword(k => k.Name("email"))
        //                .Keyword(k => k.Name("phone"))
        //                .Text(t => t.Name("realName"))
        //                .Number(n => n.Name("age").Type(NumberType.Integer))
        //                .Number(n => n.Name("gender").Type(NumberType.Integer))
        //                .Text(t => t.Name("address"))
        //                .Number(n => n.Name("status").Type(NumberType.Integer))
        //                .Date(d => d.Name("createTime"))
        //                .Date(d => d.Name("updateTime"))
        //                .Keyword(k => k.Name("tags"))
        //                .Object<Dictionary<string, object>>(o => o.Name("settings"))
        //            )
        //        )
        //    );

        //    return response.IsValidResponse;
        //}

        // 添加文档
        public async Task<bool> AddUserAsync(User user)
        {
            var response = await _client.IndexAsync(user, i => i.Index("lalla"));
            return response.IsValidResponse;
        }

        // 查询文档（by ID）
        public async Task<User?> GetUserAsync(string id)
        {
            var response = await _client.GetAsync<User>(id, g => g.Index("user"));
            return response.Found ? response.Source : null;
        }

        // 删除文档
        public async Task<bool> DeleteUserAsync(string id)
        {
            var response = await _client.DeleteAsync<User>(id, d => d.Index("user"));
            return response.IsValidResponse;
        }

        // 查询列表（分页 + 条件：状态为1）
        public async Task<List<User>> SearchUsersAsync(string? RealName = null, int page = 1, int size = 10)
        {
            #region BooleanQuery 查询 布尔查询
            {
                //var response = await _client.SearchAsync<User>(s => s
                //    .Index("users")
                //    .From((page - 1) * size)
                //    .Size(size)
                //    .Query(q => q
                //     .Bool(b => b
                //       .Must(
                //          m => m.Term(t => t.Field(f => f.Status).Value(1))
                //      )
                //    .Should(
                //        sh => sh.Match(m => m.Field(f => f.Username).Query("john")),
                //        sh => sh.Match(m => m.Field(f => f.RealName).Query("张"))
                //     )
                //    .MinimumShouldMatch(1)
                //    )
                //  )
                //);

                //var response = await _client.SearchAsync<User>(s => s
                //      .Index("users")
                //      .Query(q => q
                //          .Bool(b => b
                //              .Should(
                //                  sh => sh.Match(m => m
                //                      .Field(f => f.Username)
                //                      .Query(keyword)
                //                  ),
                //                  sh => sh.Match(m => m
                //                      .Field(f => f.RealName)
                //                      .Query(keyword)
                //                  )
                //              )
                //              .MinimumShouldMatch(1) // 至少命中一个 should 条件
                //          )
                //      )
                //  );
            }
            #endregion


            #region  Query Match 查询
            {
                //  var response3 = await _client.SearchAsync<User>(s => s
                //.Index("user")
                //.Query(q => q.Match(m => m
                //            .Field(f => f.RealName)
                //            .Query(RealName)
                //        )
                //      )
                //  );

                var response = await _client.SearchAsync<User>(s => s
                                .Index("lalla")
                                .Query(q => q.MatchAll(new MatchAllQuery())));
                var dt = response.IsValidResponse ? response.Documents.ToList() : new List<User>();
            }
            #endregion


            #region 相关性算分查询
            {
                ///相关性算分查询
                var response2 = await _client.SearchAsync<User>(s => s
                  .Index("lalla")
                  .Query(
                       x => x.FunctionScore(w => w.Query(ww => ww.MatchAll(_ => { })).Functions(f => f.Weight(10000).Filter(
                             Query.Term(new TermQuery("age") { Value = 25 })
                           )).BoostMode(FunctionBoostMode.Sum))
                    ));
                var xw = response2.Documents.ToList();
            }
            #endregion

            return null;
        }

        /// <summary>
        /// 聚合查询
        /// </summary>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public async Task<object> SerachAgretetion()
        {
            //var response = await _client.SearchAsync<User>(new SearchRequest("user")
            //{
            //    Query = Query.MatchAll(new MatchAllQuery()),
            //    Aggregations = new Dictionary<string, Aggregation>
            //      {
            //          { "agg_name", Aggregation.Max(new MaxAggregation
            //          {
            //              Field = Infer.Field<User>(x => x.Age)
            //          })}
            //      },
            //    Size = 10
            //});
            #region 聚合查询
            {
                var topLevelAggregation = Aggregation.Terms(new TermsAggregation
                {
                    Field = Infer.Field<User>(x => x.Email)
                });
                topLevelAggregation.Aggregations = new Dictionary<string, Aggregation>
                {
                     {
                        "avg_age", new MaxAggregation
                         {
                              Field = Infer.Field<User>(x => x.Age)
                         }
                     },
                     {
                        "aggs_ww", new SumAggregation
                         {
                              Field = Infer.Field<User>(x => x.Age)
                         }
                     }
                };

                var response2 = await _client.SearchAsync<User>(new SearchRequest("user")
                {
                    Query = Query.MatchAll(new MatchAllQuery()),
                    Aggregations = new Dictionary<string, Aggregation>
                    {
                        {
                            "numberRangs", topLevelAggregation
                        }
                    },
                    Size = 0
                });

                var firstnames = response2.Aggregations!.GetStringTerms("numberRangs")!;
                foreach (var bucket in firstnames.Buckets)
                {
                    var avg = bucket.Aggregations.GetMax("avg_age");
                    var sss = bucket.Aggregations.GetSum("aggs_ww");
                    Console.WriteLine($"The average age for persons named '{bucket.Key}' is {avg.Value} is {sss.Value}");
                }
            }

            {
                var response3 = await _client.SearchAsync<User>(
                      x => x.Index("user")
                      //.Query(x => x.Match(w => w.Field(ww => ww.Age).Query("")))  //限定聚合范围
                      //.Query(t => t.Term(m => m.Field(f => f.Phone).QueryName(""))) //限定聚合范围
                      .Query(x => x.MatchAll(_ => { }))
                      .Size(0) //设置为0，结果中不包含文档
                      .Aggregations(aggregations => aggregations.Add("numberRangs",
                        aggregation => aggregation.Terms(   //嵌套聚合 分组-统计最大、最小、平均值
                               terms => terms
                                   .Field(x => x.Email)
                            ).Aggregations(    //嵌套聚合 分组-统计最大、最小、平均值
                               aggregations =>
                                  aggregations.Add("aggs_ss", aggregation =>
                                  aggregation.Max(xx => xx.Field(x => x.Age)))
                                  .Add("aggs_ww",
                                  aggregation =>
                                  aggregation.Sum(xx => xx.Field(x => x.Age)))
                            )
                      ))
                    );

                var firstnames = response3.Aggregations!.GetStringTerms("numberRangs")!;
                foreach (var bucket in firstnames.Buckets)
                {
                    var avg = bucket.Aggregations.GetMax("aggs_ss")!;
                    var avgss = bucket.Aggregations.GetSum("aggs_ww")!;
                    Console.WriteLine($"The average age for persons named '{bucket.Key}' is {avg}");
                }
            }
            #endregion


            #region BooleanQuery 查询 布尔查询
            {
                //        {
                //            "query": {
                //                "bool": {
                //                    "must": [
                //                      {
                //                        "match": {
                //                            "info": "呀哎"
                //                        }
                //                    }
                //  ],
                //  "must_not": [
                //    {
                //                        "range": {
                //                            "number": {
                //                                "gt": 400,
                //        }
                //                        }
                //                    }
                //  ],
                //  "filter": [
                //    {
                //                        "geo_distance": {
                //                            "distance": "10km",
                //                            "location": {
                //                              "lat": 31.21,
                //                              "lon": 121.5
                //                            }
                //                        }
                //                    }
                //  ]
                //}
                //            }
                //        }
                var response = await _client.SearchAsync<User>(s => s
                      .Index("lala")
                      .Query(q => q
                          .Bool(b => b
                              .Must(m => m
                                  .Term(t => t.Field(s => s.Age).Value(25))
                              )
                              .Filter(f => f
                                  .GeoDistance(r => r.Field(s => s.Age).Distance("10km").Location(new LatLonGeoLocation() { Lat = 123, Lon = 123 })
                                  )
                              )
                              .Should(
                                  sh =>
                                     sh.Term(sw => sw.Field(s => s.Age).Value(""))
                              )
                              .MustNot(mn => mn
                                  //.Term(t => t.Field(s => s.Age).Value(true))
                                  .Term(t => t.Field("number").Value(true)) //不等于
                                                                            //.Range(t => t.NumberRange(x => x.Field(s => s.Age).Lte(123)))
                                 .Range(t => t.NumberRange(x => x.Field("number").Lte(123)))
                              )
                          )
                      ));
            }
            #endregion

            return null;
        }


        /// <summary>
        /// 自动补全 添加数据
        /// </summary>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public async Task<bool?> AutocompletionAddData()
        {
            var dockement = new List<Person> {
              new  Person
                  {
                      Name = "张张三",
                      NameSuggest = new List<string>
                      {
                          "张张三", "zhangsan"
                      }
                  },
               new Person
                {
                    Name = "张李四",
                    NameSuggest = new List<string>
                    {
                         "张李四", "lisi"
                    }
                },
                new Person
                {
                    Name = "张王五",
                    NameSuggest = new List<string>
                    {
                         "张王五", "wangwu"
                    }
                }
             };
            var bulkRequest = new BulkRequest("autocompletion");
            bulkRequest.Operations = new BulkOperationsCollection();
            foreach (var doc in dockement)
            {
                var operation = new BulkIndexOperation<Person>(doc);
                //{
                //    Id = doc.Id
                //};

                bulkRequest.Operations.Add(operation);
            }

            var bulkResponse = await _client.BulkAsync(bulkRequest);

            if (bulkResponse.IsValidResponse && bulkResponse.ApiCallDetails.HttpStatusCode < 300)
            {
                Console.WriteLine("✅ 批量添加成功");
            }
            else
            {
                Console.WriteLine("❌ 批量添加失败");
                Console.WriteLine(bulkResponse.ElasticsearchServerError?.ToString() ?? bulkResponse.ToString());
            }
            return true;
        }

        /// <summary>
        /// 自动补全 查询数据
        /// </summary>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public async Task<bool?> GetAutocompletionData()
        {
            //var suggestResponse = await _client.SearchAsync<Person>(s => s
            //               .Index("autocomplete_index")
            //               .SuggestField("nameSuggest").SuggestText("张").SuggestSize(10)
            //           );


            //var suggestions = suggestResponse.Suggest["name-suggest"]
            //    .SelectMany(x => x.Options)
            //    .Select(x => x.Text)
            //    .ToList();

            //foreach (var text in suggestions)
            //{
            //    Console.WriteLine("✅ 自动补全建议: " + text);
            //}
            #region 补全查询
            {
                var json = @"{
                       ""suggest"": {
                         ""titlesugget"": {
                           ""text"": ""张"",
                           ""completion"": {
                             ""field"": ""nameSuggest"",
                             ""skip_duplicates"": true,
                             ""size"": 10
                           }
                         }
                       }
                     }";
                var response = await _client.Transport.RequestAsync<StringResponse>(Elastic.Transport.HttpMethod.GET,
                     "/autocompletion/_search",
                     PostData.String(json)
                 );
                using var doc = JsonDocument.Parse(response.Body);
                string formatted = JsonSerializer.Serialize(doc.RootElement, new JsonSerializerOptions
                {
                    WriteIndented = true,
                    Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping // ✅ 防止中文转义
                });
                //var options = doc.RootElement
                //             .GetProperty("suggest")
                //             .GetProperty("titlesugget")[0]
                //             .GetProperty("options");
                //Console.WriteLine(formatted);

                // 处理响应
                if (response.ApiCallDetails.HttpStatusCode == 200)
                {
                    Console.WriteLine("✅ 查询成功");
                    Console.WriteLine(response.Body); // 原始 JSON 响应
                }
                else
                {
                    Console.WriteLine($"❌ 查询失败：{response.ApiCallDetails.HttpStatusCode}");
                    Console.WriteLine(response.Body);
                }
            }
            #endregion
            return true;
        }
    }
}
